package org.example.mutithread.future;

import com.google.common.util.concurrent.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class FutureUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(FutureUtil.class);

    private ExecutorService executor;
    private ListeningExecutorService guavaExecutor;

    private <T> FutureUtil(Callable<T>... tasks) {
        executor = Executors.newFixedThreadPool(tasks.length);
        guavaExecutor = MoreExecutors.listeningDecorator(executor);
    }

    private <T> FutureUtil(int poolSize) {
        executor = Executors.newFixedThreadPool(poolSize);
        guavaExecutor = MoreExecutors.listeningDecorator(executor);
    }

    public static <T> FutureUtil getInstance(int poolSize) {
        return new FutureUtil(poolSize);
    }

    public static <T> FutureUtil getInstance(Callable<T>... tasks) {
        return new FutureUtil(tasks);
    }


    public <T> void submit( ITaskRs itaskRs,Callable<T>... tasks) {
        List<ListenableFuture<T>> list = new ArrayList<>();
        for (Callable task : tasks) {
            ListenableFuture<T> future = guavaExecutor.submit(task);
            list.add(future);
        }
        ListenableFuture<List<T>> listListenableFuture = Futures.allAsList(list);

        Futures.addCallback(listListenableFuture, new FutureCallback<List<T>>() {
            @Override
            public void onSuccess(List<T> result) {
                LOGGER.info("onSuccess {}", result.toString());
                itaskRs.onSuccess(result);
                close();
            }

            @Override
            public void onFailure(Throwable t) {
                LOGGER.error("onFailure {}", t);
                itaskRs.onFailure(t);
                close();
            }

            private void close() {
                guavaExecutor.shutdown();
                executor.shutdown();
            }
        }, guavaExecutor);
    }


}
